package com.power.sifa.statistics.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.plf.common.utils.FileUtil;
import com.plf.core.base.model.Ha_attachment;
import com.plf.core.base.service.Ha_attachmentService;
import com.power.sifa.aop.service.SMService;
import com.power.sifa.correction.dao.Crc_personDao;
import com.power.sifa.correction.dao.Cre_warningDao;
import com.power.sifa.correction.dao.Cre_workDao;
import com.power.sifa.correction.dao.Cre_work_recordDao;
import com.power.sifa.correction.model.*;
import com.power.sifa.correction.model.enumeration.St_workEnum;
import com.power.sifa.correction.model.enumeration.Tp_crc_userEnum;
import com.power.sifa.statistics.model.pageInfo.WarningPageInfo;
import com.power.sifa.statistics.service.CorrectionCountService;
import com.power.sifa.statistics.service.CorrectionWarningService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CorrectionWarningServiceImpl implements CorrectionWarningService {

    @Autowired
    private Crc_personDao crcPersonDao;
    @Autowired
    private Cre_warningDao creWarningDao;
    @Autowired
    private Cre_workDao creWorkDao;
    @Autowired
    private Cre_work_recordDao creWorkRecordDao;
    @Autowired
    private CorrectionCountService correctionCountService;
    @Autowired
    private Ha_attachmentService ha_attachmentService;
    @Autowired
    private SMService smService;

    @Value("${power.file.http-schema:''}")
    private String httpSchema;
    @Value("${power.file.domain:''}")
    private String domain;

    /**
     * 申请材料附件生成路径
     */
    @Value("${power.file-path:#{null}}")
    private String filePath;

    @Override
    public void generateWord(String warnId, HttpServletResponse response) {
        try {
            Map<String, Object> params = this.findWarningRecordVO(warnId);
            String fileName = params.get("number") + "-" + warnId;
            File file = new File(this.filePath + "/" + fileName + ".docx");
//            Map<String, Object> params = this.findWarningRecordVO(warnId);
            if (params == null) return;

            Configure tables = Configure.builder()
                    .bind("warning", new LoopRowTableRenderPolicy())
                    .bind("disposeList", new LoopRowTableRenderPolicy())
                    .build();

            // 模板路径
            Resource resource = new ClassPathResource("template-word/" + "CorrectionWarningRecord.docx");
            XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream(), tables).render(params);

            // 将文档写入到响应输出流
            FileOutputStream fos = new FileOutputStream(file);
            template.write(fos);

            template.close();

            FileUtil.download(response, file.getAbsolutePath(), fileName);
        } catch (IOException e) {
            log.error("生成word异常{}", e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            log.error("下载异常{}", e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public void generateWords(List<String> warnIds, HttpServletResponse response) {
        File tempDir = new File(this.filePath + "/" + NanoIdUtils.randomNanoId());
        tempDir.mkdirs();

        ExecutorService executor = Executors.newFixedThreadPool(20); // 创建一个拥有5个线程的线程池
        List<Future<Void>> futures = new ArrayList<>();

        for (String warnId : warnIds) {
            log.warn("预警处置记录表导出任务开始执行{}", warnId);
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    Map<String, Object> params = creWarningDao.findWarningRecordVO(warnId);
                    if (CollectionUtil.isEmpty(params)) {
                        throw new RuntimeException("预警处置记录表导出任务执行失败:" + warnId + "查询结果为空！");
                    }
                    // 头像
                    String avatarUrl = creWarningDao.getFileUrl(params.get("avatar").toString());

                    params.put("avatar", Pictures.ofUrl(avatarUrl)
                            .size(95, 130).create());
                    // 预警信息
                    List<Cre_record_ga> gaList = correctionCountService.getCreRecordGaList((Integer) params.get("gaid"), 100);
                    if (CollectionUtil.isNotEmpty(gaList)) {
                        List<Map<String, Object>> warnings = new ArrayList<>();
                        List<CompletableFuture<Void>> futureImgs = new ArrayList<>();
                        for (Cre_record_ga ga : gaList) {
                            Map<String, Object> warn = new HashMap<>();
                            warn.put("warning_time", String.valueOf(ga.getRectime()));
                            warn.put("warning_arr", ga.getAddr());
                            // todo
                            CompletableFuture<Void> futureImg = CompletableFuture.runAsync(() -> {
                                PictureRenderData warnImg = Pictures.ofUrl(creWarningDao.getFileUrl(ga.getPhoto()))
                                        .size(75, 50).create();
                                warn.put("warning_img", warnImg);
                                warnings.add(warn);
                            });
                            futureImgs.add(futureImg);
                        }
                        CompletableFuture.allOf(futureImgs.toArray(new CompletableFuture[0])).join();
                        params.put("warning", warnings);
                    } else {
                        params.put("warning", null);
                    }
                    // 处置流程
                    List<Cre_work_record> recordList = creWorkRecordDao.findListByWarnId(warnId);
                    if (CollectionUtil.isNotEmpty(recordList)) {
                        List<WarningPageInfo> disposeList = recordList.stream()
                                .map(record -> new WarningPageInfo(String.valueOf(record.getExectime()), record.getRecord()))
                                .collect(Collectors.toList());
                        params.put("disposeList", disposeList);
                    } else {
                        params.put("disposeList", null);
                    }
                    String fileName = params.get("number") + "-" + warnId;
                    File file = new File(tempDir.getAbsolutePath() + "/" + fileName + ".docx");
                    if (params == null) return;

                    Configure tables = Configure.builder()
                            .bind("warning", new LoopRowTableRenderPolicy())
                            .bind("disposeList", new LoopRowTableRenderPolicy())
                            .build();

                    // 模板路径
                    Resource resource = new ClassPathResource("template-word/" + "CorrectionWarningRecord.docx");
                    XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream(), tables).render(params);

                    // 将生成的Word文档保存到临时文件夹中
                    FileOutputStream fos = new FileOutputStream(file);
                    template.write(fos);
                    log.warn("预警处置记录表导出任务执行完成{}", warnId);

                    template.close(); // 关闭模板
                    fos.close();

                } catch (IOException e) {
                    log.error("生成word异常{}", e.getMessage());
                    e.printStackTrace();
                }
            });
            futures.add(future);
        }
        for (Future<Void> future : futures) {
            try {
                CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
            } catch (Exception e) {
                // 处理异常
                log.error("预警处置记录表导出任务执行异常{}", e.getMessage());
                e.printStackTrace();
            }
        }
        executor.shutdown(); // 关闭线程池
        // 将临时文件夹中的所有Word文档打包成zip文件
        try {
            // 压缩文件为zip格式
            FileUtil.toZip(tempDir.getAbsolutePath(), true);
            // 下载材料文件
            FileUtil.download(response, tempDir.getAbsolutePath() + ".zip", tempDir.getAbsolutePath() + ".zip");

        } catch (Exception e) {
            log.error("打包zip文件异常{}", e.getMessage());
            e.printStackTrace();
        } finally {
            // 删除材料文件
            FileUtil.delDir(tempDir);
            FileUtil.delDir(new File(tempDir.getAbsolutePath() + ".zip"));
        }
    }

    /**
     * 写入临时文件
     *
     * @param warnId
     * @param tempDir
     * @return
     */
    private void temporaryFiles(String warnId, File tempDir, ExecutorService executor, List<Future<Void>> futures) {
        try {
            Map<String, Object> params = findWarningRecordVO(warnId, executor, futures);
            String fileName = params.get("number") + "-" + warnId;
            File file = new File(tempDir.getAbsolutePath() + "/" + fileName + ".docx");
            if (params == null) return;

            Configure tables = Configure.builder()
                    .bind("warning", new LoopRowTableRenderPolicy())
                    .bind("disposeList", new LoopRowTableRenderPolicy())
                    .build();

            // 模板路径
            Resource resource = new ClassPathResource("template-word/" + "CorrectionWarningRecord.docx");
            XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream(), tables).render(params);

            // 将生成的Word文档保存到临时文件夹中
            FileOutputStream fos = new FileOutputStream(file);
            template.write(fos);
            log.warn("预警处置记录表导出任务执行完成{}", warnId);

            template.close(); // 关闭模板
            fos.close();

        } catch (IOException e) {
            log.error("生成word异常{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 表格数据封装
     *
     * @param warnId
     * @return
     */
    private Map<String, Object> findWarningRecordVO(String warnId) {
        Map<String, Object> warningRecordVO = creWarningDao.findWarningRecordVO(warnId);
        try {
            warningRecordVO.put("cardno", smService.decrypt(warningRecordVO.get("cardno").toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (CollectionUtil.isEmpty(warningRecordVO)) {
            return null;
        }
        // 头像
        String avatarUrl = creWarningDao.getFileUrl(warningRecordVO.get("avatar").toString());

        PictureRenderData pictureRenderData = Pictures.ofUrl(avatarUrl).size(95, 130).create();

        warningRecordVO.put("avatar", Pictures.ofUrl(avatarUrl)
                .size(95, 130).create());
        // 预警信息
        List<Cre_record_ga> gaList = correctionCountService.getCreRecordGaList((Integer) warningRecordVO.get("gaid"), 100);
        if (CollectionUtil.isNotEmpty(gaList)) {
            List<Map<String, Object>> warnings = new ArrayList<>();
            for (Cre_record_ga ga : gaList) {
                Map<String, Object> warn = new HashMap<>();
                warn.put("warning_time", String.valueOf(ga.getRectime()));
                warn.put("warning_arr", ga.getAddr());
                warn.put("warning_img", Pictures.ofUrl(creWarningDao.getFileUrl(ga.getPhoto()))
                        .size(75, 50).create());
                warnings.add(warn);
            }
            warningRecordVO.put("warning", warnings);
        } else {
            warningRecordVO.put("warning", null);
        }
        // 处置流程
        List<Cre_work_record> recordList = creWorkRecordDao.findListByWarnId(warnId);
        if (CollectionUtil.isNotEmpty(recordList)) {
            List<WarningPageInfo> disposeList = recordList.stream()
                    .map(record -> new WarningPageInfo(String.valueOf(record.getExectime()), record.getRecord()))
                    .collect(Collectors.toList());
            warningRecordVO.put("disposeList", disposeList);
        } else {
            warningRecordVO.put("disposeList", null);
        }
        return warningRecordVO;
    }

    private Map<String, Object> findWarningRecordVO(String warnId, ExecutorService executor, List<Future<Void>> futures) {
        Map<String, Object> warningRecordVO = creWarningDao.findWarningRecordVO(warnId);
        if (CollectionUtil.isEmpty(warningRecordVO)) {
            return null;
        }
        // 头像
        String avatarUrl = creWarningDao.getFileUrl(warningRecordVO.get("avatar").toString());

        warningRecordVO.put("avatar", Pictures.ofUrl(avatarUrl)
                .size(95, 130).create());
        // 预警信息
        List<Cre_record_ga> gaList = correctionCountService.getCreRecordGaList((Integer) warningRecordVO.get("gaid"), 100);
        if (CollectionUtil.isNotEmpty(gaList)) {
            List<Map<String, Object>> warnings = new ArrayList<>();
            for (Cre_record_ga ga : gaList) {
                Map<String, Object> warn = new HashMap<>();
                warn.put("warning_time", String.valueOf(ga.getRectime()));
                warn.put("warning_arr", ga.getAddr());
                // todo
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    PictureRenderData warnImg = Pictures.ofUrl(creWarningDao.getFileUrl(ga.getPhoto()))
                            .size(75, 50).create();
                    warn.put("warning_img", warnImg);
                    warnings.add(warn);
                });
                futures.add(future);
            }

            warningRecordVO.put("warning", warnings);
        } else {
            warningRecordVO.put("warning", null);
        }
        // 处置流程
        List<Cre_work_record> recordList = creWorkRecordDao.findListByWarnId(warnId);
        if (CollectionUtil.isNotEmpty(recordList)) {
            List<WarningPageInfo> disposeList = recordList.stream()
                    .map(record -> new WarningPageInfo(String.valueOf(record.getExectime()), record.getRecord()))
                    .collect(Collectors.toList());
            warningRecordVO.put("disposeList", disposeList);
        } else {
            warningRecordVO.put("disposeList", null);
        }
        return warningRecordVO;
    }

    /**
     * 表格数据封装（弃用）
     *
     * @param warnId
     * @return
     */
    private Map<String, Object> getStringObjectMap(String warnId) {
        Map<String, Object> params = new HashMap<>();
        Cre_warning warning = creWarningDao.getById(warnId);
        if (warning == null) return null;
        Crc_person person = crcPersonDao.getById(warning.getPerid());
        if (person == null) return null;
        params.put("name", person.getName());
        params.put("gender", person.getGender() == 1200 ? "男" : "女");
        params.put("number", person.getId());
        params.put("crctype", Tp_crc_userEnum.getTypeNameByValue(person.getCrctype()));
        List<Map<String, Object>> departList = crcPersonDao.findDepartByAdid(person.getDeptid());
        params.put("deptname", CollectionUtil.isNotEmpty(departList) ? departList.get(0).get("orgname") : "");
        params.put("phone", person.getPhone());
        Map<String, Ha_attachment> haAttachmentsByIds = ha_attachmentService.getHa_attachmentsByIds(Arrays.asList(person.getAvatar()));
        if (ObjectUtil.isNotNull(haAttachmentsByIds)) {
            Ha_attachment haAttachment = haAttachmentsByIds.get(person.getAvatar());
            person.setAvatarUrl(haAttachment.getPath());
            params.put("avatar", Pictures.ofUrl(person.getAvatarUrl())
                    .size(95, 130).create());
        }

        params.put("rectime", warning.getRectime());

        // todo 手机定位，暂时未对接移动，先用预警地点
        params.put("addr", warning.getAddr());

        Cre_work creWork = creWorkDao.getByWarnId(warnId);
        params.put("verify", St_workEnum.getStatusNameByValue(creWork.getStatus()));

        List<Cre_work_record> recordList = creWorkRecordDao.findListByWarnId(warnId);
        List<WarningPageInfo> disposeList = new ArrayList<>();
        for (Cre_work_record record : recordList) {
            disposeList.add(WarningPageInfo.builder()
                    .dispose_time(String.valueOf(record.getExectime()))
                    .dispose_opinion(record.getRecord())
                    .build());
        }
        params.put("disposeList", disposeList);

        Optional<Cre_work_record> disposal = recordList.stream()
                .filter(record -> record.getIspis() == 3201 && ObjectUtil.isNotNull(record.getUserid()))
                .max(Comparator.comparing(Cre_work_record::getExectime));
        if (disposal.isPresent()) {
            params.put("disposal", disposal.get().getRecord());
        } else {
            params.put("punishment", null);
        }

        Optional<Cre_work_record> punishment = recordList.stream()
                .filter(record -> record.getIspis() == 3200 && ObjectUtil.isNotNull(record.getUserid()))
                .max(Comparator.comparing(Cre_work_record::getExectime));
        if (punishment.isPresent()) {
            params.put("punishment", punishment.get().getRecord());
        } else {
            params.put("punishment", null);
        }

        List<Cre_record_ga> creRecordGaList = correctionCountService.getCreRecordGaList(warning.getGaid(), 100);
        List<Map<String, Object>> warnings = new ArrayList<>();
        Map<String, Object> imgs = new HashMap<>();
        for (Cre_record_ga ga : creRecordGaList) {
            Map<String, Object> warn = new HashMap<>();
            warn.put("warning_time", String.valueOf(ga.getRectime()));
            warn.put("warning_arr", ga.getAddr());
            String fileUrl = ha_attachmentService.getFileUrl(ga.getPhoto());
            warn.put("warning_img", Pictures.ofUrl(fileUrl)
                    .size(75, 50).create());
            warnings.add(warn);
        }
        params.put("warning", warnings);
        return params;
    }

    /**
     * 合并图片（弃用）
     *
     * @param imageURLs
     * @return
     */
    public BufferedImage imgList(List<URL> imageURLs) {
        try {
            // 添加更多图片URL

            List<BufferedImage> images = new ArrayList<>();

            // 读取所有图片
            for (URL imageURL : imageURLs) {
                BufferedImage image = ImageIO.read(imageURL);
                images.add(image);
            }

            // 确定目标宽度（可以根据需要调整）
            int targetWidth = images.stream().mapToInt(BufferedImage::getWidth).max().orElse(0);

            // 计算缩放比例和缩放后的高度
            List<BufferedImage> scaledImages = new ArrayList<>();
            List<Integer> scaledHeights = new ArrayList<>();

            for (BufferedImage image : images) {
                double scale = (double) targetWidth / image.getWidth();
                int scaledHeight = (int) (image.getHeight() * scale);
                scaledHeights.add(scaledHeight);

                BufferedImage scaledImage = new BufferedImage(targetWidth, scaledHeight, BufferedImage.TYPE_3BYTE_BGR);
                Graphics2D g2d = scaledImage.createGraphics();
                g2d.drawImage(image.getScaledInstance(targetWidth, scaledHeight, Image.SCALE_SMOOTH), 0, 0, null);
                g2d.dispose();

                scaledImages.add(scaledImage);
            }

            // 计算合并后的高度
            int combinedHeight = scaledHeights.stream().mapToInt(Integer::intValue).sum();

            // 创建合并后的BufferedImage对象
            BufferedImage combinedImage = new BufferedImage(targetWidth, combinedHeight, BufferedImage.TYPE_3BYTE_BGR);

            ImageIO.write(combinedImage, "jpg", new File("D:\\WorkSpace\\sifa\\dateDemo\\word\\testImage6.jpg"));

            // 绘制合并后的图片
            Graphics2D combinedGraphics = combinedImage.createGraphics();
            int y = 0;

            for (int i = 0; i < scaledImages.size(); i++) {
                BufferedImage scaledImage = scaledImages.get(i);
                combinedGraphics.drawImage(scaledImage, 0, y, null);
                y += scaledHeights.get(i);
            }

            combinedGraphics.dispose();

            // 保存合并后的图片
            ImageIO.write(combinedImage, "jpg", new File("D:\\WorkSpace\\sifa\\dateDemo\\word\\testImage5.jpg"));
            return combinedImage;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
